package com.shuda.business.monitor.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shuda.business.monitor.dto.*;
import com.shuda.business.monitor.entity.DataMonitorEntity;
import com.shuda.business.monitor.entity.MonitorAlertConfigEntity;
import com.shuda.business.monitor.mapper.DataMonitorMapper;
import com.shuda.business.monitor.mapper.MonitorAlertConfigMapper;
import com.shuda.business.monitor.service.DataMonitorService;
import com.shuda.business.monitor.vo.MonitorAlertConfigVO;
import com.shuda.common.dto.PageDTO;
import com.shuda.common.utils.PageResult;
import com.shuda.common.core.exception.BusinessException;
import com.shuda.common.security.utils.SecurityUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 数据监控服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class DataMonitorServiceImpl extends ServiceImpl<DataMonitorMapper, DataMonitorEntity> 
        implements DataMonitorService {

    private final DataMonitorMapper dataMonitorMapper;
    private final MonitorAlertConfigMapper monitorAlertConfigMapper;

    /**
     *
     * 解析时间范围
     * @param timeRange 时间范围字符串，支持"start,end"或"start - end"
     * @return LocalDateTime[] [start, end]
     * @author ink
     * @Description: 解析失败时默认最近24小时
     * @date 2025-11-09 10:40
     */
    private LocalDateTime[] parseTimeRange(String timeRange) {
        LocalDateTime end = LocalDateTime.now();
        LocalDateTime start = end.minusHours(24);
        if (timeRange != null && !timeRange.trim().isEmpty()) {
            String[] parts;
            if (timeRange.contains(" - ")) {
                parts = timeRange.split(" - ");
            } else if (timeRange.contains(",")) {
                parts = timeRange.split(",");
            } else {
                parts = new String[]{timeRange, timeRange};
            }
            DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            try {
                if (parts.length >= 1 && parts[0] != null && !parts[0].isBlank()) {
                    start = LocalDateTime.parse(parts[0].trim(), fmt);
                }
                if (parts.length >= 2 && parts[1] != null && !parts[1].isBlank()) {
                    end = LocalDateTime.parse(parts[1].trim(), fmt);
                }
            } catch (Exception ignore) { }
        }
        return new LocalDateTime[]{start, end};
    }

    /**
     *
     * 获取监控统计信息
     * @param channelId 渠道ID
     * @param schemeId 方案ID
     * @param timeRange 时间范围字符串
     * @return MonitorStatisticsDTO
     * @author ink
     * @Description: 解析时间范围并计算成功率
     * @date 2025-11-09 10:40
     */
    @Override
    public MonitorStatisticsDTO getMonitorStatistics(String channelId, String schemeId, String timeRange) {
        LocalDateTime[] range = parseTimeRange(timeRange);
        Map<String, Object> statistics = dataMonitorMapper.getMonitorStatistics(range[0], range[1]);

        MonitorStatisticsDTO dto = new MonitorStatisticsDTO();
        dto.setTotalDataCount(Optional.ofNullable(statistics.get("totalDataCount")).map(obj -> Long.parseLong(obj.toString())).orElse(0L));
        dto.setProcessedDataCount(Optional.ofNullable(statistics.get("processedDataCount")).map(obj -> Long.parseLong(obj.toString())).orElse(0L));
        dto.setSuccessDataCount(Optional.ofNullable(statistics.get("successDataCount")).map(obj -> Long.parseLong(obj.toString())).orElse(0L));
        dto.setFailedDataCount(Optional.ofNullable(statistics.get("failedDataCount")).map(obj -> Long.parseLong(obj.toString())).orElse(0L));
        dto.setExceptionDataCount(Optional.ofNullable(statistics.get("exceptionDataCount")).map(obj -> Long.parseLong(obj.toString())).orElse(0L));

        if (dto.getProcessedDataCount() > 0) {
            double successRate = (double) dto.getSuccessDataCount() / dto.getProcessedDataCount() * 100;
            dto.setSuccessRate(String.format("%.2f%%", successRate));
        } else {
            dto.setSuccessRate("0.00%");
        }

        dto.setStartTime(range[0]);
        dto.setEndTime(range[1]);
        return dto;
    }

    /**
     *
     * 分页查询监控数据列表
     * @param pageDTO 分页参数
     * @param channelId 渠道ID
     * @param schemeId 方案ID
     * @param status 状态
     * @param startTime 开始时间字符串
     * @param endTime 结束时间字符串
     * @return PageResult<DataMonitorDTO>
     * @author ink
     * @Description: 构造条件并分页查询
     * @date 2025-11-09 10:40
     */
    @Override
    public PageResult<DataMonitorDTO> getMonitorDataPage(PageDTO pageDTO, String channelId, String schemeId, String status, String startTime, String endTime) {
        LambdaQueryWrapper<DataMonitorEntity> wrapper = new LambdaQueryWrapper<>();
        if (channelId != null && !channelId.isBlank()) {
            wrapper.eq(DataMonitorEntity::getChannelId, channelId);
        }
        if (schemeId != null && !schemeId.isBlank()) {
            wrapper.eq(DataMonitorEntity::getSchemeId, schemeId);
        }
        if (status != null && !status.isBlank()) {
            wrapper.eq(DataMonitorEntity::getStatus, status);
        }
        if (startTime != null && endTime != null && !startTime.isBlank() && !endTime.isBlank()) {
            try {
                DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                LocalDateTime st = LocalDateTime.parse(startTime.trim(), fmt);
                LocalDateTime et = LocalDateTime.parse(endTime.trim(), fmt);
                wrapper.between(DataMonitorEntity::getCreateTime, st, et);
            } catch (Exception ignore) { }
        }
        
        wrapper.orderByDesc(DataMonitorEntity::getCreateTime);
        
        IPage<DataMonitorEntity> page = new Page<>(pageDTO.getPageNum(), pageDTO.getPageSize());
        IPage<DataMonitorEntity> resultPage = this.page(page, wrapper);
        
        List<DataMonitorDTO> dtoList = resultPage.getRecords().stream().map(entity -> {
            DataMonitorDTO dto = new DataMonitorDTO();
            dto.setId(entity.getId());
            dto.setChannelId(entity.getChannelId());
            dto.setSchemeId(entity.getSchemeId());
            dto.setDataId(entity.getDataId());
            dto.setDataContent(entity.getDataContent());
            dto.setStatus(entity.getStatus());
            dto.setProcessResult(entity.getProcessResult());
            dto.setErrorMessage(entity.getErrorMessage());
            dto.setProcessingTime(entity.getProcessingTime());
            dto.setCreateTime(entity.getCreateTime());
            dto.setProcessTime(entity.getProcessTime());
            return dto;
        }).collect(Collectors.toList());
        
        return new PageResult<>(dtoList, resultPage.getTotal(), resultPage.getCurrent(), resultPage.getSize());
    }

    /**
     *
     * 获取实时监控数据
     * @param channelId 渠道ID（可空）
     * @param schemeId 方案ID（可空）
     * @return Map<String,Object> 包含key:list
     * @author ink
     * @Description: 最近1小时的最新100条
     * @date 2025-11-09 10:40
     */
    @Override
    public Map<String, Object> getRealtimeMonitorData(String channelId, String schemeId) {
        // 获取最近1小时的数据
        LocalDateTime oneHourAgo = LocalDateTime.now().minusHours(1);
        
        LambdaQueryWrapper<DataMonitorEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.ge(DataMonitorEntity::getCreateTime, oneHourAgo)
               .orderByDesc(DataMonitorEntity::getCreateTime)
               .last("LIMIT 100");
        if (channelId != null && !channelId.isBlank()) {
            wrapper.eq(DataMonitorEntity::getChannelId, channelId);
        }
        if (schemeId != null && !schemeId.isBlank()) {
            wrapper.eq(DataMonitorEntity::getSchemeId, schemeId);
        }
        
        List<DataMonitorEntity> entities = this.list(wrapper);
        
        List<DataMonitorDTO> list = entities.stream().map(entity -> {
            DataMonitorDTO dto = new DataMonitorDTO();
            dto.setId(entity.getId());
            dto.setChannelId(entity.getChannelId());
            dto.setSchemeId(entity.getSchemeId());
            dto.setDataId(entity.getDataId());
            dto.setDataContent(entity.getDataContent());
            dto.setStatus(entity.getStatus());
            dto.setProcessResult(entity.getProcessResult());
            dto.setErrorMessage(entity.getErrorMessage());
            dto.setProcessingTime(entity.getProcessingTime());
            dto.setCreateTime(entity.getCreateTime());
            dto.setProcessTime(entity.getProcessTime());
            return dto;
        }).collect(Collectors.toList());
        Map<String, Object> result = new HashMap<>();
        result.put("list", list);
        return result;
    }

    /**
     * 获取渠道分发统计
     * @param timeRange 时间范围
     * @return List<Map<String,Object>>
     */
    @Override
    public List<Map<String, Object>> getChannelDistributionStatistics(String timeRange) {
        LocalDateTime[] range = parseTimeRange(timeRange);
        return dataMonitorMapper.getChannelDistributionStatistics(range[0], range[1]);
    }

    @Override
    public Map<String, Object> getProcessingSuccessRate(String timeRange) {
        LocalDateTime[] range = parseTimeRange(timeRange);
        return dataMonitorMapper.getProcessingSuccessRate(range[0], range[1]);
    }

    @Override
    public Map<String, Object> getExceptionStatistics(String timeRange) {
        LocalDateTime[] range = parseTimeRange(timeRange);
        return dataMonitorMapper.getExceptionStatistics(range[0], range[1]);
    }

    @Override
    public Map<String, Object> getPerformanceMonitorData(String timeRange) {
        LocalDateTime[] range = parseTimeRange(timeRange);
        Map<String, Object> performanceData = dataMonitorMapper.getPerformanceMonitorData(range[0], range[1]);
        performanceData = performanceData == null ? new HashMap<>() : new HashMap<>(performanceData);
        performanceData.putIfAbsent("cpuUsage", Math.random() * 100);
        performanceData.putIfAbsent("memoryUsage", Math.random() * 100);
        performanceData.putIfAbsent("diskUsage", Math.random() * 100);
        performanceData.putIfAbsent("networkUsage", Math.random() * 100);
        return performanceData;
    }

    @Override
    public Map<String, Object> getDataQualityReport(String timeRange) {
        LocalDateTime[] range = parseTimeRange(timeRange);
        Map<String, Object> qualityData = dataMonitorMapper.getDataQualityReport(range[0], range[1]);
        return qualityData == null ? Collections.emptyMap() : qualityData;
    }

    @Override
    public String exportMonitorData(String channelId, String schemeId, String startTime, String endTime, String format) {
        // 占位实现，后续补充导出逻辑
        return "";
    }

    /** 获取监控告警配置列表（按VO筛选） */
    public List<MonitorAlertConfigDTO> getAlertConfigList(MonitorAlertConfigVO queryVO) {
        LambdaQueryWrapper<MonitorAlertConfigEntity> wrapper = new LambdaQueryWrapper<>();
        
        if (queryVO.getAlertName() != null) {
            wrapper.like(MonitorAlertConfigEntity::getAlertName, queryVO.getAlertName());
        }
        
        if (queryVO.getAlertType() != null) {
            wrapper.eq(MonitorAlertConfigEntity::getAlertType, queryVO.getAlertType());
        }
        
        if (queryVO.getAlertLevel() != null) {
            wrapper.eq(MonitorAlertConfigEntity::getAlertLevel, queryVO.getAlertLevel());
        }
        
        if (queryVO.getAlertMethod() != null) {
            wrapper.eq(MonitorAlertConfigEntity::getAlertMethod, queryVO.getAlertMethod());
        }
        
        if (queryVO.getEnabled() != null) {
            wrapper.eq(MonitorAlertConfigEntity::getEnabled, queryVO.getEnabled());
        }
        
        wrapper.orderByDesc(MonitorAlertConfigEntity::getCreateTime);
        
        List<MonitorAlertConfigEntity> entities = monitorAlertConfigMapper.selectList(wrapper);
        
        return entities.stream().map(entity -> {
            MonitorAlertConfigDTO dto = new MonitorAlertConfigDTO();
            dto.setId(entity.getId());
            dto.setAlertName(entity.getAlertName());
            dto.setAlertType(entity.getAlertType());
            dto.setThreshold(entity.getThreshold());
            dto.setAlertLevel(entity.getAlertLevel());
            dto.setAlertMethod(entity.getAlertMethod());
            dto.setAlertRecipients(entity.getAlertRecipients());
            dto.setEnabled(entity.getEnabled() == 1);
            dto.setDescription(entity.getDescription());
            dto.setCreateTime(entity.getCreateTime());
            dto.setUpdateTime(entity.getUpdateTime());
            return dto;
        }).collect(Collectors.toList());
    }

    /** 更新监控告警配置（DTO版本） */
    @Transactional
    public MonitorAlertConfigDTO updateAlertConfig(Long id, MonitorAlertConfigDTO configDTO) {
        MonitorAlertConfigEntity entity = monitorAlertConfigMapper.selectById(id);
        if (entity == null) {
            throw new BusinessException("告警配置不存在");
        }
        
        entity.setAlertName(configDTO.getAlertName());
        entity.setAlertType(configDTO.getAlertType());
        entity.setThreshold(configDTO.getThreshold());
        entity.setAlertLevel(configDTO.getAlertLevel());
        entity.setAlertMethod(configDTO.getAlertMethod());
        entity.setAlertRecipients(configDTO.getAlertRecipients());
        entity.setEnabled(configDTO.getEnabled() ? 1 : 0);
        entity.setDescription(configDTO.getDescription());
        entity.setUpdateBy(SecurityUtils.getCurrentUsername());
        
        monitorAlertConfigMapper.updateById(entity);
        
        configDTO.setId(entity.getId());
        configDTO.setUpdateTime(entity.getUpdateTime());
        return configDTO;
    }

    /**
     * 获取监控告警配置（接口要求Map返回）
     * @return Map<String,Object> 包含items
     */
    @Override
    public Map<String, Object> getAlertConfig() {
        List<MonitorAlertConfigEntity> entities = monitorAlertConfigMapper.selectList(new LambdaQueryWrapper<>());
        List<MonitorAlertConfigDTO> items = entities.stream().map(entity -> {
            MonitorAlertConfigDTO dto = new MonitorAlertConfigDTO();
            dto.setId(entity.getId());
            dto.setAlertName(entity.getAlertName());
            dto.setAlertType(entity.getAlertType());
            dto.setThreshold(entity.getThreshold());
            dto.setAlertLevel(entity.getAlertLevel());
            dto.setAlertMethod(entity.getAlertMethod());
            dto.setAlertRecipients(entity.getAlertRecipients());
            dto.setEnabled(entity.getEnabled() == 1);
            dto.setDescription(entity.getDescription());
            dto.setCreateTime(entity.getCreateTime());
            dto.setUpdateTime(entity.getUpdateTime());
            return dto;
        }).collect(Collectors.toList());
        Map<String, Object> result = new HashMap<>();
        result.put("items", items);
        return result;
    }

    /**
     * 更新监控告警配置（接口要求Map入参）
     */
    @Override
    public void updateAlertConfig(Map<String, Object> config) {
        Object idObj = config.get("id");
        if (idObj == null) {
            throw new BusinessException("缺少配置ID");
        }
        Long id = Long.parseLong(idObj.toString());
        MonitorAlertConfigDTO dto = new MonitorAlertConfigDTO();
        dto.setAlertName(Objects.toString(config.get("alertName"), null));
        dto.setAlertType(Objects.toString(config.get("alertType"), null));
        dto.setThreshold(Objects.toString(config.get("threshold"), null));
        dto.setAlertLevel(Objects.toString(config.get("alertLevel"), null));
        dto.setAlertMethod(Objects.toString(config.get("alertMethod"), null));
        dto.setAlertRecipients(Objects.toString(config.get("alertRecipients"), null));
        Object enabledObj = config.get("enabled");
        if (enabledObj != null) {
            dto.setEnabled(Boolean.parseBoolean(enabledObj.toString()));
        }
        dto.setDescription(Objects.toString(config.get("description"), null));
        updateAlertConfig(id, dto);
    }
}